package com.meirengu.webview.controller;

import com.alibaba.fastjson.JSONObject;
import com.meirengu.common.RedisClient;
import com.meirengu.common.StatusCode;
import com.meirengu.model.Result;
import com.meirengu.utils.HttpUtil;
import com.meirengu.webview.model.KwWxSubscribe;
import com.meirengu.webview.service.KwWxInteractiveService;
import com.meirengu.webview.service.KwWxSubscribeService;
import com.meirengu.webview.service.WxMqService;
import com.meirengu.webview.utils.SHA1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.*;

/**
 * ${DESCRIPTION}
 * 花花有钱
 *
 * @author Mao
 * @create 2017-12-19 12:27
 */
@Controller
@RequestMapping("wx")
public class WechatController {

    @Autowired
    private KwWxSubscribeService kwWxSubscribeService;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private WxMqService wxMqService;

    @Autowired
    private KwWxInteractiveService kwWxInteractiveService;


    Logger logger = LoggerFactory.getLogger(WechatController.class);


    @RequestMapping("url")
    public void url(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String token = "";//公众号基本配置，服务器配置启用的Token令牌
        try {
            token = "kwdvipToken";
        } catch (Exception e) {
            ;
        }
        // 微信服务器将发送GET请求到填写的URL上,这里需要判定是否为GET请求
        boolean isGet = request.getMethod().toLowerCase().equals("get");
        logger.info("wx kwd url verify, http method is:", request.getMethod());
        if (isGet) {
            // 验证URL真实性

            String tntInstId = request.getParameter("tntInstId");
            System.out.println("tntInstId: " + tntInstId);
            String scene = request.getParameter("scene");
            System.out.println("scene: " + scene);
            String signature = request.getParameter("signature");// 微信加密签名
            String timestamp = request.getParameter("timestamp");// 时间戳
            String nonce = request.getParameter("nonce");// 随机数
            String echostr = request.getParameter("echostr");// 随机字符串
            List<String> params = new ArrayList<String>();
            params.add(token);
            params.add(timestamp);
            params.add(nonce);
            // 1. 将token、timestamp、nonce三个参数进行字典序排序
            Collections.sort(params, new Comparator<String>() {
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
                }
            });
            // 2. 将三个参数字符串拼接成一个字符串进行sha1加密
            String temp = SHA1.encode(params.get(0) + params.get(1) + params.get(2));
            if (temp.equals(signature)) {
                logger.info("signature success,temp={},signatrue={}", new Object[]{temp, signature});
                response.getWriter().write(echostr);
            } else {
                logger.info("signature failure,temp={},signatrue={}", new Object[]{temp, signature});
            }
        } else {
            // 处理接收消息
            boolean isreturn = false;
            logger.info("1.收到微信服务器消息");
            Map<String, String> wxdata = parseXml(request);
            logger.info(wxdata.toString());
            String openId = wxdata.get("FromUserName");
            if (wxdata.get("MsgType") != null) {
                if ("event".equals(wxdata.get("MsgType"))) {
                    logger.info("2.1解析消息内容为：事件推送");
                    if ("subscribe".equals(wxdata.get("Event"))) {
                        logger.info("2.2用户第一次关注 返回true哦");
                        isreturn = true;
                        //存储记录  subscribe
                        Map<String, Object> map = new HashMap<>();
                        map.put("fromUserName", openId);
                        map.put("toUserName", "gh_895ae09a34b3");
                        int count = kwWxSubscribeService.getCount(map);
                        String userUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + redisClient.get("WXACCESSTOKEN") + "&openid=" + openId + "&lang=zh_CN";
                        HttpUtil.HttpResult hr1 = HttpUtil.doGet(userUrl);
                        String content1 = new String(hr1.getContent().getBytes("ISO-8859-1"), "UTF-8");
                        logger.info("content1:{}" + content1);
                        JSONObject jsonObject = JSONObject.parseObject(content1);
                        String nikeName = jsonObject.getString("nickname");
                        KwWxSubscribe kwWxSubscribe = new KwWxSubscribe();
                        kwWxSubscribe.setToUserName(wxdata.get("ToUserName"));
                        kwWxSubscribe.setFromUserName(openId);
                        kwWxSubscribe.setCreateTime(new Date(Long.parseLong(wxdata.get("CreateTime")) * 1000));
                        kwWxSubscribe.setMsgType(wxdata.get("MsgType"));
                        kwWxSubscribe.setEvent(wxdata.get("Event"));
                        kwWxSubscribe.setNikeName(nikeName);
                        if (count < 1) {
                            kwWxSubscribeService.insert(kwWxSubscribe);
                            wxMqService.sendHhWxDelayMsg(kwWxSubscribe.getId(), openId,wxdata.get("ToUserName"));
                        } else {
                            List<KwWxSubscribe> list = new ArrayList<>();
                            list = kwWxSubscribeService.getModel(map);
                            wxMqService.sendHhWxDelayMsg(list.get(0).getId(), openId,wxdata.get("ToUserName"));
                        }
                        logger.info("=====>id:{}", kwWxSubscribe.getId());
                        //回复
                        ServletOutputStream outputStream = response.getOutputStream();
                        outputStreamWrite(outputStream, wxResult(wxdata.get("FromUserName"), wxdata.get("ToUserName")));
                        return;
                    } else if ("CLICK".equals(wxdata.get("Event"))) {
                        logger.info("2.2用户第一次关注 返回true哦");
                        //回复
                        kwWxInteractiveService.insert(wxdata);
                        ServletOutputStream outputStream = response.getOutputStream();
                        outputStreamWrite(outputStream, wxClickResult(wxdata.get("FromUserName"), wxdata.get("ToUserName")));
                    }
                } else if ("text".equals(wxdata.get("MsgType"))) {
                    logger.info("2.2解析消息内容为：自动回复消息");
                    //回复
                    kwWxInteractiveService.insert(wxdata);
                    ServletOutputStream outputStream = response.getOutputStream();
                    outputStreamWrite(outputStream, wxAutoResult(wxdata.get("FromUserName"), wxdata.get("ToUserName")));
                } else {
                    logger.info("2.2解析消息内容为：其他");
                    //回复
                    kwWxInteractiveService.insert(wxdata);
                }
            }
            logger.info("3.2  回复空");

        }
    }

    /**
     * 用DOM方式组装返给微信的xml数据
     *
     * @return String
     * @author maoruxin
     * @date 2016年6月30日
     */
    public static String wxResult(String fromUserNameValue, String toUserNameValue) {
        String resultString = "";
        Document doc;
        Element xml;
        Element fromUserName;
        Element toUserName;
        Element createTime;
        Element msgType;
        Element content;
        try {
            //得到DOM解析器的工厂实例
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            //从DOM工厂中或得DOM解析器
            DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
            //创建文档树模型对象
            doc = dbBuilder.newDocument();
            if (doc != null) {
                xml = doc.createElement("xml");
                fromUserName = doc.createElement("ToUserName");
                toUserName = doc.createElement("FromUserName");
                createTime = doc.createElement("CreateTime");
                msgType = doc.createElement("MsgType");
                content = doc.createElement("Content");
                fromUserName.appendChild(doc.createTextNode(fromUserNameValue));
                toUserName.appendChild(doc.createTextNode(toUserNameValue));
                createTime.appendChild(doc.createTextNode(System.currentTimeMillis() + ""));
                msgType.appendChild(doc.createTextNode("text"));
                StringBuilder contentBuffer = new StringBuilder();
                contentBuffer.append("嗨，终于等到你，小妹在此恭候多时！\n\n");
                contentBuffer.append("1000-3000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=1\">【点击这里】</a>").append("\n\n");
                contentBuffer.append("3000-10000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=3\">【点击这里】</a>").append("\n\n");
                contentBuffer.append("10000-50000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=4\">【点击这里】</a>").append("\n\n");
                contentBuffer.append("更多贷款，可直接在对话框回复“贷款”了解！");
                String contentStr = contentBuffer.toString();
                content.appendChild(doc.createTextNode(contentStr));
                xml.appendChild(fromUserName);
                xml.appendChild(toUserName);
                xml.appendChild(createTime);
                xml.appendChild(msgType);
                xml.appendChild(content);
                doc.appendChild(xml);
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                DOMSource source = new DOMSource(doc);
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                transformer.transform(source, new StreamResult(bos));
                resultString = bos.toString();
            }

        } catch (Exception e) {
            // TODO: handle exception
        }
        return resultString;
    }

    /**
     * 用DOM方式组装返给微信的xml数据
     *
     * @return String
     * @author maoruxin
     * @date 2016年6月30日
     */
    public static String wxClickResult(String fromUserNameValue, String toUserNameValue) {
        String resultString = "";
        Document doc;
        Element xml;
        Element fromUserName;
        Element toUserName;
        Element createTime;
        Element msgType;
        Element content;
        try {
            //得到DOM解析器的工厂实例
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            //从DOM工厂中或得DOM解析器
            DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
            //创建文档树模型对象
            doc = dbBuilder.newDocument();
            if (doc != null) {
                xml = doc.createElement("xml");
                fromUserName = doc.createElement("ToUserName");
                toUserName = doc.createElement("FromUserName");
                createTime = doc.createElement("CreateTime");
                msgType = doc.createElement("MsgType");
                content = doc.createElement("Content");
                fromUserName.appendChild(doc.createTextNode(fromUserNameValue));
                toUserName.appendChild(doc.createTextNode(toUserNameValue));
                createTime.appendChild(doc.createTextNode(System.currentTimeMillis() + ""));
                msgType.appendChild(doc.createTextNode("text"));
                StringBuilder contentBuffer = new StringBuilder();
                contentBuffer.append("根据您的资质，我们为您推荐以下产品：\n\n");
                contentBuffer.append("1000-3000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=1\">【点击这里】</a>").append("\n\n");
                contentBuffer.append("3000-10000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=3\">【点击这里】</a>").append("\n\n");
                contentBuffer.append("10000-50000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=4\">【点击这里】</a>").append("\n\n");
                String contentStr = contentBuffer.toString();
                content.appendChild(doc.createTextNode(contentStr));
                xml.appendChild(fromUserName);
                xml.appendChild(toUserName);
                xml.appendChild(createTime);
                xml.appendChild(msgType);
                xml.appendChild(content);
                doc.appendChild(xml);
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                DOMSource source = new DOMSource(doc);
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                transformer.transform(source, new StreamResult(bos));
                resultString = bos.toString();
            }

        } catch (Exception e) {
            // TODO: handle exception
        }
        return resultString;
    }


    /**
     * 用DOM方式组装返给微信的xml数据
     *
     * @return String
     * @author maoruxin
     * @date 2016年6月30日
     */
    public static String wxAutoResult(String fromUserNameValue, String toUserNameValue) {
        String resultString = "";
        Document doc;
        Element xml;
        Element fromUserName;
        Element toUserName;
        Element createTime;
        Element msgType;
        Element content;
        try {
            //得到DOM解析器的工厂实例
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            //从DOM工厂中或得DOM解析器
            DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
            //创建文档树模型对象
            doc = dbBuilder.newDocument();
            if (doc != null) {
                xml = doc.createElement("xml");
                fromUserName = doc.createElement("ToUserName");
                toUserName = doc.createElement("FromUserName");
                createTime = doc.createElement("CreateTime");
                msgType = doc.createElement("MsgType");
                content = doc.createElement("Content");
                fromUserName.appendChild(doc.createTextNode(fromUserNameValue));
                toUserName.appendChild(doc.createTextNode(toUserNameValue));
                createTime.appendChild(doc.createTextNode(System.currentTimeMillis() + ""));
                msgType.appendChild(doc.createTextNode("text"));
                StringBuilder contentBuffer = new StringBuilder();
                contentBuffer.append("更多额度  ");
                contentBuffer.append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=1\">【点击这里】</a>").append("\n\n");
                String contentStr = contentBuffer.toString();
                content.appendChild(doc.createTextNode(contentStr));
                xml.appendChild(fromUserName);
                xml.appendChild(toUserName);
                xml.appendChild(createTime);
                xml.appendChild(msgType);
                xml.appendChild(content);
                doc.appendChild(xml);
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                DOMSource source = new DOMSource(doc);
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                transformer.transform(source, new StreamResult(bos));
                resultString = bos.toString();
            }

        } catch (Exception e) {
            // TODO: handle exception
        }
        return resultString;
    }

    /**
     * 数据流输出
     *
     * @param outputStream
     * @param text
     * @return
     */
    private boolean outputStreamWrite(OutputStream outputStream, String text) {
        try {
            outputStream.write(text.getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
        return true;
    }


    /**
     * 解析微信发来的请求（XML）
     *
     * @param request
     * @return Map<String, String>
     * @author maoruxin
     * @date 2016年6月30日
     */
    public static Map<String, String> parseXml(HttpServletRequest request) {
        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();

        // 从request中取得输入流
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            XMLInputFactory factory = XMLInputFactory.newInstance();
            XMLEventReader reader = factory.createXMLEventReader(inputStream);
            while (reader.hasNext()) {
                XMLEvent event = reader.nextEvent();
                if (event.isStartElement()) {
                    String tagName = event.asStartElement().getName()
                            .toString();
                    if (!tagName.equals("xml")) {
                        String text = reader.getElementText();
                        map.put(tagName, text);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XMLStreamException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return map;
    }


    @RequestMapping("test")
    public void test(@RequestParam(value = "openId", defaultValue = "oZOkk1laSU6eqxXhMadmqIYmaVsE", required = false) String openId) throws Exception {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("touser", openId);
        jsonObject.put("msgtype", "text");
        JSONObject contentJson = new JSONObject();
        StringBuilder contentBuffer = new StringBuilder();
        contentBuffer.append("嗨，终于等到你，小妹在此恭候多时！\n\n");
        contentBuffer.append("1000-3000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=1\">【点击这里】</a>").append("\n\n");
        contentBuffer.append("3000-10000  \ue231 ").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market?quotaType=3\">【点击这里】</a>").append("\n\n");
        contentBuffer.append("[红包]点我,").append("<a href=\"https://mdzj139.com/loan/index.html?cid=channel_wxtg#/market\">一键领取5000元急救金</a>");
        contentBuffer.append("更多贷款，可直接在对话框回复“贷款”了解！");
        String contentStr = contentBuffer.toString();
        contentJson.put("content", contentStr);
        jsonObject.put("text", contentJson);


        String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + "_AqJWmkk4_IpVFVmxNpDQGrVex1PEG41L7mKLoNqpiRfL-4VqjJyzeU14xNtSX1PsPDtsxJEFnODd5fmRmeNTvf0eOY6kyuLTBmRJO81n0_iRtw3p-rdkG1RcGTADTGfAGAJZM";
        HttpUtil.HttpResult hr = HttpUtil.doPost(url, jsonObject.toString());
        System.out.println(hr.toString());
    }

    @RequestMapping("getWxAccessToken")
    @ResponseBody
    public Result getWxAccessToken() {
        Result result = new Result();
        try {
            kwWxSubscribeService.wxAccessToken();
            result.setCode(StatusCode.OK);
            result.setMsg(StatusCode.codeMsgMap.get(StatusCode.OK));
        } catch (Exception e) {
            result.setCode(StatusCode.INTERNAL_SERVER_ERROR);
            result.setMsg(StatusCode.codeMsgMap.get(StatusCode.INTERNAL_SERVER_ERROR));
        }
        return result;
    }

    @RequestMapping("createMenu")
    public void createMenu() throws Exception {
        kwWxSubscribeService.createMenu();
    }


    @RequestMapping("getUserList")
    public void getUserList() throws Exception {
        kwWxSubscribeService.getUserList();
    }

    @RequestMapping("sendTemplateMsg")
    public void sendTemplateMsg(@RequestParam(value = "name", required = true) String name) throws Exception {
        kwWxSubscribeService.sendTemplateMsg(name);
    }

    @RequestMapping("sendTemplateMsgMultiple")
    public void sendTemplateMsgMultiple(@RequestParam(value = "name", required = true) String name) throws Exception {
        kwWxSubscribeService.sendTemplateMsgMultiple(name);
    }

}
